/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
#ifndef GIMI_MESSAGEFILTER_H
#define GIMI_MESSAGEFILTER_H

#include <string>
#include <set>
#include <map>

#include "gimiutils.h"

namespace gimi {

struct WantedService {
  WantedService();
  WantedService(const std::string descr,
                const std::string loc);
  ~WantedService();
  
  inline std::string getDescription() const { return description; };
  inline std::string getLocation() const { return location; };
  
  std::string description;
  std::string location;
};

typedef std::set<int> t_wantedSenders;
typedef t_wantedSenders::iterator t_wantedSendersIterator;
typedef t_wantedSenders::const_iterator t_wantedSendersConstIterator;
  
typedef std::map<int, WantedService> t_wantedMinorTypes;
typedef t_wantedMinorTypes::iterator t_wantedMinorTypesIterator;
typedef t_wantedMinorTypes::const_iterator t_wantedMinorTypesConstIterator;
typedef std::pair< int, WantedService > t_wantedMinorTypesPair;

typedef std::map< int, t_wantedMinorTypes > t_wantedTypes;
typedef t_wantedTypes::iterator t_wantedTypesIterator;
typedef t_wantedTypes::const_iterator t_wantedTypesConstIterator;
typedef std::pair< int, t_wantedMinorTypes > t_wantedTypesPair;

/**
 * \class GIMIMessageFilter
 * 
 * A message filtering system for GIMI.
 * If user wants to receive messages only from some senders or messages with
 * certain major and minor types, they are defined here.
 *
 * Currently all messages are accepted when no filters are defined. (same for
 * senders & types)
 */
class GIMIMessageFilter {
  public:
    GIMIMessageFilter();
    ~GIMIMessageFilter();

    bool addWantedSender(const int clientId);
    bool removeWantedSender(const int clientId);
    bool clearWantedSenders();

    /**
     * Adds accepted datatypes to servicelist.
     * Returns number of added datatypes.
     */
    int listWantedTypes(t_serviceList &serviceList);
    
    /**
     * Checks if given senderId is wanted. If definition list is empty, all
     * senders are accepted.
     *
     * \return True if sender is wanted.
     */
    bool isWantedSender(const int clientId);

    /** 
     * Checks if a Major/Minor pair is in the list
     * of wanted types.
     * \note This function differs from the 'isWantedType' because
     * it returns the absolute truth about wether the queried
     * type is registered or not. No logic is applied on query result.
     * 
     * @return                  'true' if the value is registered (is found),
     *                          'false' if it is not.
     */
    bool isRegisteredType(const int majorTypeId,
                          const int minorTypeId);

    bool addWantedType(const int majorTypeId,
                       const int minorTypeId = GIMI_IGNOREMINORTYPE,
                       const std::string serviceDescription = "",
                       const std::string serviceLocation = "");
    bool removeWantedType(const int majorTypeId,
                          const int minorTypeId = GIMI_IGNOREMINORTYPE);
    bool clearWantedTypes();

    /**
     * Checks if given type is wanted. If definition lists are empty, all
     * types are accepted.
     * 
     * \return True if message is wanted.
     */
    bool isWantedType(const int majorTypeId,
                      const int minorTypeId);
    
  private:
    // Prevents use of copy constructors
    GIMIMessageFilter(const GIMIMessageFilter& filter);
    const GIMIMessageFilter& operator= (const GIMIMessageFilter& right);
    
    ownMutexHandle filterMutex;
    
    t_wantedSenders wantedSenders;
    t_wantedTypes wantedTypes;
};

}

#endif
